package it.rap.applications.movimenti.ricerche.widget;

import it.rap.application.logic.mappers.MovimentoLogic;
import it.rap.applications.persistence.entities.contoCorrente.ContoCorrente;
import it.rap.applications.persistence.entities.movimento.Movimento;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableColorProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;

public class MovimentoDataContainer extends Composite  {

	private static final long serialVersionUID = 3915689843296617976L;
	
	public static final String ID_MOVIMENTO 		= "ID movimento";
	public static final String DATA_CONTABILE 		= "Data Contabile";
	public static final String DATA_VALUTA 			= "Data valuta";
	public static final String ADDEBITO 			= "Addebito";
	public static final String ACCREDITO			= "Accredito";
	public static final String DESCRIZIONE 			= "Descrizione";
	public static final String DESCRIZIONE_COMPLETA	= "Descrizione completa";
	public static Integer 	   DEFAULT_ACCOUNTS		= 1;
	
	public static final String[] PROPS = { ID_MOVIMENTO, DATA_CONTABILE, DATA_VALUTA, ACCREDITO, ADDEBITO, DESCRIZIONE, DESCRIZIONE_COMPLETA };
	private final Composite	contentComp;
	private DataNavigator dataNavigator = null;
	private Composite compositeDataNavigator = null; 
	
	private Text currentDataLimitText;
	private Integer currentDataLimit = 20;
	private Text currentDataOffsetText;
	private Integer currentDataOffset = 0;
	
	private BigDecimal totaleMovimenti = new BigDecimal("0");
	
	private TableViewer tv = null; 
	private Table uiTableProperties;

	private List<Movimento> propertiesList= new ArrayList<Movimento>();
	private CellEditor[] editors = new CellEditor[7];
	
	private ContoCorrente cc = new ContoCorrente();

	
	/**
	 * @wbp.parser.constructor
	 */
	public MovimentoDataContainer(Composite parent) {
		super(parent, SWT.NONE);
		setLayoutData(new GridData(GridData.FILL, SWT.FILL, true, true ));
		contentComp = createComposite();
	}

	public MovimentoDataContainer(Composite parent, ContoCorrente cc) {
		super(parent, SWT.NONE);
		setLayoutData(new GridData(GridData.FILL, SWT.FILL, true, true ));
		contentComp = createComposite();
		this.cc = cc;
	}

	private Composite createComposite() {
		
		GridLayout gl_dataComposite = new GridLayout(1, false);
		gl_dataComposite.verticalSpacing = 0;
		gl_dataComposite.marginWidth = 0;
		gl_dataComposite.marginHeight = 0;
		gl_dataComposite.horizontalSpacing = 0;
		setLayout(gl_dataComposite);
	    
		compositeDataNavigator = new Composite(this, SWT.NONE);
		GridData gd_compositeDataNavigator = new GridData(SWT.LEFT, SWT.FILL, true, false, 1, 1);
		compositeDataNavigator.setLayoutData(gd_compositeDataNavigator);
		RowLayout rl_compositeDataNavigator = new RowLayout(SWT.HORIZONTAL);
		compositeDataNavigator.setLayout( rl_compositeDataNavigator);
		compositeDataNavigator.setVisible(true);
		//compositeDataNavigator.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false, 2, 1));
		
		Button previousRangeDataButton = new Button(compositeDataNavigator, SWT.NONE);
		previousRangeDataButton.addSelectionListener(new SelectionAdapter() {
			
			private static final long serialVersionUID = 6024936608021483098L;

			@Override
			public void widgetSelected(SelectionEvent e) {
				if( currentDataOffset >= currentDataLimit ){
					currentDataOffset = currentDataOffset - currentDataLimit;
					currentDataOffsetText.setText( ""+currentDataOffset );
					currentDataLimitText.setText( ""+currentDataLimit );
					currentDataOffsetText.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
					currentDataLimitText.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
					loadData();
					dataNavigator.setCurrentDataLimit( new BigDecimal( currentDataLimit ) );
					dataNavigator.setCurrentDataOffset( new BigDecimal(currentDataOffset) );
					dataNavigator.setTotaleMovimenti( totaleMovimenti );
					dataNavigator.refresh();
				}
			}
		});
		previousRangeDataButton.setText("<");
		
		currentDataOffsetText = new Text(compositeDataNavigator, SWT.BORDER );
		currentDataOffsetText.setLayoutData(new RowData(27, SWT.DEFAULT));
		currentDataOffsetText.addModifyListener(new ModifyListener() {
			
			private static final long serialVersionUID = -8546729160323808058L;

			public void modifyText(ModifyEvent event) {
				currentDataOffset = Integer.parseInt( currentDataOffsetText.getText() );
				currentDataOffsetText.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);				
			}
		});
		currentDataOffsetText.setText( ""+currentDataOffset );
		
		Label _l = new Label( compositeDataNavigator, SWT.NONE);
		_l.setText(" - ");
		
		currentDataLimitText = new Text(compositeDataNavigator, SWT.BORDER );
		currentDataLimitText.setLayoutData(new RowData(27, SWT.DEFAULT));
		currentDataLimitText.addModifyListener(new ModifyListener() {
			
			private static final long serialVersionUID = 211724654169235244L;

			public void modifyText(ModifyEvent event) {
				currentDataLimit = Integer.parseInt( currentDataLimitText.getText() );				
				currentDataLimitText.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
			}
		});
		currentDataLimitText.setText( ""+currentDataLimit );
		
		Button nextRangeDataButton = new Button(compositeDataNavigator, SWT.NONE);
		nextRangeDataButton.addSelectionListener(new SelectionAdapter() {
			
			private static final long serialVersionUID = 3742953187019857365L;

			@Override
			public void widgetSelected(SelectionEvent e) {
				if (totaleMovimenti.compareTo( new BigDecimal( currentDataOffset + currentDataLimit )) >= 0 ){
					currentDataOffset = currentDataOffset + currentDataLimit;
					currentDataOffsetText.setText( ""+currentDataOffset );
					currentDataLimitText.setText( ""+currentDataLimit );
					currentDataOffsetText.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
					currentDataLimitText.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
					loadData();
					dataNavigator.setCurrentDataLimit( new BigDecimal( currentDataLimit ) );
					dataNavigator.setCurrentDataOffset( new BigDecimal(currentDataOffset) );
					dataNavigator.setTotaleMovimenti( totaleMovimenti );
					dataNavigator.refresh();
				} else {
					//estraggo i rimanenti
				}
			}
		});
		nextRangeDataButton.setText(">");
		
		dataNavigator = new DataNavigator(compositeDataNavigator , new BigDecimal( currentDataOffset ), new BigDecimal( currentDataLimit ), totaleMovimenti );
		dataNavigator.setVisible(false);
	    
	    Composite composite = new Composite(this, SWT.NONE);
	    composite.setLayout(new GridLayout(1, false));
	    composite.setLayoutData(new GridData(GridData.FILL, SWT.FILL, true, true ));
	    
	    tv = new TableViewer(composite, SWT.BORDER | SWT.FULL_SELECTION );
	    tv.setData( RWT.CUSTOM_VARIANT, "tvContainer" );
	    uiTableProperties = tv.getTable();
	    uiTableProperties.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
	    
	    tv.setContentProvider(new MovimentoContentProvider());
	    tv.setLabelProvider(new MovimentoLabelProvider());
	    tv.setInput( propertiesList );
	    
	    TableColumn tableColumn_1 = new TableColumn(uiTableProperties, SWT.CENTER);
	    tableColumn_1.setWidth( 10 * ID_MOVIMENTO.length() );
	    tableColumn_1.setText( ID_MOVIMENTO );
	    TableColumn tableColumn_2 = new TableColumn(uiTableProperties, SWT.CENTER);
	    tableColumn_2.setWidth( 11 * DATA_CONTABILE.length() );
	    tableColumn_2.setText( DATA_CONTABILE );				
	    TableColumn tableColumn_3 = new TableColumn(uiTableProperties, SWT.CENTER);
	    tableColumn_3.setWidth( 11 * DATA_VALUTA.length() );
	    tableColumn_3.setText( DATA_VALUTA );
	    TableColumn tableColumn_4 = new TableColumn(uiTableProperties, SWT.CENTER);
	    tableColumn_4.setWidth( 11 * ACCREDITO.length() );
	    tableColumn_4.setText( ACCREDITO );
	    TableColumn tableColumn_5 = new TableColumn(uiTableProperties, SWT.CENTER);
	    tableColumn_5.setWidth( 11 * ADDEBITO.length() );
	    tableColumn_5.setText( ADDEBITO );
	    
	    TableColumn tableColumn_6 = new TableColumn(uiTableProperties, SWT.CENTER);
	    tableColumn_6.setWidth( 25 * DESCRIZIONE.length() );
	    tableColumn_6.setText( DESCRIZIONE );
	    
	    TableColumn tableColumn_7 = new TableColumn(uiTableProperties, SWT.CENTER);
	    tableColumn_7.setWidth( 50 * DESCRIZIONE_COMPLETA.length() );
	    tableColumn_7.setText( DESCRIZIONE_COMPLETA );
	    
	    uiTableProperties.setLinesVisible(true);
	    uiTableProperties.setHeaderVisible(true);
	    
		tv.setColumnProperties(PROPS);
		tv.setCellModifier(new MovimentoCellModifier(tv));
		editors[1] = new TextCellEditor(uiTableProperties);
		editors[2] = new TextCellEditor(uiTableProperties);
		editors[3] = new TextCellEditor(uiTableProperties);
		editors[4] = new TextCellEditor(uiTableProperties);
		editors[5] = new TextCellEditor(uiTableProperties);
		editors[6] = new TextCellEditor(uiTableProperties);
		tv.setCellEditors(editors);
				
	    for (int i = 0, n = uiTableProperties.getColumnCount(); i < n; i++) {
	      uiTableProperties.getColumn(i).pack();
	    } 
		editors[0] = null;
		
		return this;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.swt.widgets.Control#setVisible(boolean)
	 */
	@Override
	public void setVisible(boolean visible) {		
		super.setVisible(visible);
		dataNavigator.setVisible(visible);
		compositeDataNavigator.setVisible(visible);
	}

	public void loadData(){
		try {		
			MovimentoLogic mLogic = new MovimentoLogic();
			List<Movimento> mList = mLogic.selectAll(cc, currentDataOffset, currentDataLimit);
			propertiesList.clear();	  
			if ( mList != null && mList.size() > 0  ){
				propertiesList.addAll( mList );
				Collections.sort(propertiesList, new MovimentoComparable());
				Collections.reverse( propertiesList );
				tv.refresh();
			} else { 
				 MessageBox messageBox = new MessageBox( getShell(), SWT.OK );
				 messageBox.setText( "Info" );
				 messageBox.setMessage( "Nessun record trovato" );
				 messageBox.open();
			}
		} catch( Exception e){
			e.printStackTrace();
		}
	}
	/**
	 * @return the cc
	 */
	public ContoCorrente getCc() {
		return cc;
	}

	/**
	 * @param cc the cc to set
	 */
	public void setCc(ContoCorrente cc) {
		this.cc = cc;
	}

	public Composite getContentComp() {
		return contentComp;
	}

	/**
	 * @return the currentDataLimitText
	 */
	public Text getCurrentDataLimitText() {
		return currentDataLimitText;
	}

	/**
	 * @param currentDataLimitText the currentDataLimitText to set
	 */
	public void setCurrentDataLimitText(Text currentDataLimitText) {
		this.currentDataLimitText = currentDataLimitText;
	}

	/**
	 * @return the currentDataLimit
	 */
	public Integer getCurrentDataLimit() {
		return currentDataLimit;
	}

	/**
	 * @param currentDataLimit the currentDataLimit to set
	 */
	public void setCurrentDataLimit(Integer currentDataLimit) {
		this.currentDataLimit = currentDataLimit;
	}

	/**
	 * @return the currentDataOffsetText
	 */
	public Text getCurrentDataOffsetText() {
		return currentDataOffsetText;
	}

	/**
	 * @param currentDataOffsetText the currentDataOffsetText to set
	 */
	public void setCurrentDataOffsetText(Text currentDataOffsetText) {
		this.currentDataOffsetText = currentDataOffsetText;
	}

	/**
	 * @return the currentDataOffset
	 */
	public Integer getCurrentDataOffset() {
		return currentDataOffset;
	}

	/**
	 * @param currentDataOffset the currentDataOffset to set
	 */
	public void setCurrentDataOffset(Integer currentDataOffset) {
		this.currentDataOffset = currentDataOffset;
	}

	/**
	 * @return the totaleMovimenti
	 */
	public BigDecimal getTotaleMovimenti() {
		return totaleMovimenti;
	}

	/**
	 * @param totaleMovimenti the totaleMovimenti to set
	 */
	public void setTotaleMovimenti(BigDecimal totaleMovimenti) {
		this.totaleMovimenti = totaleMovimenti;
	}

	public void addMovimento(Movimento p) {
		propertiesList.add(p);
	    tv.refresh();
	}

	/**
	 * @return the propertiesList
	 */
	public List<Movimento> getPropertiesList() {
		return propertiesList;
	}

	/**
	 * @param propertiesList the propertiesList to set
	 */
	public void setPropertiesList(List<Movimento> propertiesList) {
		this.propertiesList = propertiesList;
	}
	
	public void refresh() {
		tv.refresh();
		currentDataOffsetText.setText( ""+currentDataOffset );
		currentDataLimitText.setText( ""+currentDataLimit );
		currentDataOffsetText.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
		currentDataLimitText.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
		dataNavigator.refresh();
	}

	/**
	 * @return the dataNavigator
	 */
	public DataNavigator getDataNavigator() {
		return dataNavigator;
	}

	/**
	 * @param dataNavigator the dataNavigator to set
	 */
	public void setDataNavigator(DataNavigator dataNavigator) {
		this.dataNavigator = dataNavigator;
	}
}

class MovimentoComparable implements Comparator<Movimento>{
	public int compare(Movimento arg0, Movimento arg1) {
		return arg0.getDataContabile().compareTo( arg1.getDataContabile() );
	}
} 

class MovimentoContentProvider implements IStructuredContentProvider {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public Object[] getElements(Object inputElement) {
		return ((List<?>) inputElement).toArray();
	}

	public void dispose() {
	}

	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
	}
}


class MovimentoLabelProvider implements ITableLabelProvider,  ITableColorProvider  {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
	
	public Image getColumnImage(Object element, int columnIndex) {
		return null;
	}

	public String getColumnText(Object element, int columnIndex) {
		Movimento p = (Movimento) element;
		switch (columnIndex) {
		case 0:
			return p.getIdMovimento()==null?"":Float.toString(p.getIdMovimento());
		case 1:
			return p.getDataContabile()==null?"":sdf.format(p.getDataContabile());
		case 2:
			return p.getDataValuta()==null?"":sdf.format(p.getDataValuta());
		case 3:
			return p.getAccredito()==null?"":Float.toString( p.getAccredito() );			
		case 4:
			return  p.getAddebito()==null?"":Float.toString(p.getAddebito());
		case 5:
			return p.getDescrizione()==null?"":p.getDescrizione();
		case 6:
			return p.getDescrizioneCompleta()==null?"":p.getDescrizioneCompleta();
			
		}
		return null;
	}

	public void addListener(ILabelProviderListener listener) {
	}

	public void dispose() {
	}

	public boolean isLabelProperty(Object element, String property) {
		return false;
	}

	public void removeListener(ILabelProviderListener listener) {
	}

	public Color getForeground(Object element, int columnIndex) {
		switch (columnIndex) {
		case 3:
			return new Color(Display.getCurrent(), 0, 255, 0 );		
		case 4:
			return new Color(Display.getCurrent(), 255, 0, 0 );		
		}
		return null;
	}

	public Color getBackground(Object element, int columnIndex) {
		return null;
	}
}

class MovimentoCellModifier implements ICellModifier {
	  private Viewer viewer;
	  private SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
	  
	  public MovimentoCellModifier(Viewer viewer) {
	    this.viewer = viewer;
	  }

	  public boolean canModify(Object element, String property) {
	    return true;
	  }

	  public Object getValue(Object element, String property) {
	    Movimento p = (Movimento) element;
	    if (MovimentoDataContainer.ID_MOVIMENTO.equals(property))
	      return p.getIdMovimento()==null?"":p.getIdMovimento().toString();
	    else if (MovimentoDataContainer.DATA_CONTABILE.equals(property))
	      return p.getDataContabile()==null?"":sdf.format( p.getDataContabile() );
	    else if (MovimentoDataContainer.DATA_VALUTA.equals(property))
	      return p.getDataValuta()==null?"":sdf.format( p.getDataValuta() );
	    else if (MovimentoDataContainer.ACCREDITO.equals(property))
		      return p.getAccredito()==null?"":p.getAccredito().toString();
	    else if (MovimentoDataContainer.ADDEBITO.equals(property))
		      return p.getAddebito()==null?"":p.getAddebito().toString();
	    else if (MovimentoDataContainer.DESCRIZIONE.equals(property))
		      return p.getDescrizione()==null?"":p.getDescrizione();
	    else if (MovimentoDataContainer.DESCRIZIONE_COMPLETA.equals(property))
		      return p.getDescrizioneCompleta()==null?"":p.getDescrizioneCompleta();
	    else
	      return null;
	  }

	  public void modify(Object element, String property, Object value) {
	    if (element instanceof Item) element = ((Item) element).getData();

	    Movimento p = (Movimento) element;
	    if (MovimentoDataContainer.ID_MOVIMENTO.equals(property))
	      p.setIdMovimento( value==null?null:Float.parseFloat( (String)value ) );	   
	    else if (MovimentoDataContainer.DATA_CONTABILE.equals(property)){	
	    	try {
				p.setDataContabile( sdf.parse( (String) value ) );
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    }
	    
	    else if (MovimentoDataContainer.DATA_VALUTA.equals(property)){
			try {
				p.setDataValuta( sdf.parse( (String) value ) );
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	    }
		else if (MovimentoDataContainer.ACCREDITO.equals(property))
		      p.setAccredito( value==null||value.equals("")?null:Float.parseFloat( (String)value ));
	    else if (MovimentoDataContainer.ADDEBITO.equals(property))
		      p.setAddebito( value==null||value.equals("")?null:Float.parseFloat( (String)value ));
	    else if (MovimentoDataContainer.DESCRIZIONE.equals(property))
		      p.setDescrizione( value==null||value.equals("")?null:(String) value);
	    else if (MovimentoDataContainer.DESCRIZIONE_COMPLETA.equals(property))
		      p.setDescrizioneCompleta( value==null||value.equals("")?null:(String) value);
	    viewer.refresh();
	  }
	}